#include <iostream>
#include "httplib.h"
#include "add_contacts.pb.h"
#include "contact_exception.hh"
#include <sys/types.h>
#include <unistd.h>

using namespace httplib;

static unsigned int random_char()
{
    // ⽤于随机数引擎获得随机种⼦
    std::random_device rd;
    // mt19937是c++11新特性，它是⼀种随机数算法，⽤法与rand()函数类似，但是mt19937具有速度快，周期⻓的特点
    // 作⽤是⽣成伪随机数
    std::mt19937 gen(rd());
    // 随机⽣成⼀个整数i 范围[0, 255]
    std::uniform_int_distribution<> dis(0, 255);
    return dis(gen);
}

// ⽣成 UUID （通⽤唯⼀标识符）
static std::string generate_hex(const unsigned int len)
{
    std::stringstream ss;
    // ⽣成 len 个16进制随机数，将其拼接⽽成
    for (auto i = 0; i < len; i++)
    {
        const auto rc = random_char();
        std::stringstream hexstream;
        hexstream << std::hex << rc;
        auto hex = hexstream.str();
        ss << (hex.length() < 2 ? '0' + hex : hex);
    }
    return ss.str();
}

void print_contacts(add_contacts::add_contacts_request& req)
{
    std::cout << "联系人姓名：" << req.name() << std::endl;
    std::cout << "联系人年龄：" << req.age() << std::endl;
    for (int j = 0; j < req.phone_size() ; j++) {
        const add_contacts::add_contacts_request_Phone& phone = req.phone(j);
        std::cout << "联系人电话" << j+1 << ":" << phone.number();
        // 联系人电话1:1311111  (MP)
        std::cout << "   (" << phone.PhoneType_Name(phone.type()) << ")" << std::endl;
    }
}

int main()
{
    std::cout << "--------服务启动--------" << std::endl;
    Server server;
    // 1.反序列化req req->body
    server.Post("/contacts/add", [](const Request &req, Response &res){
        std::cout << "接收到Post请求" << std::endl;
        add_contacts::add_contacts_request request;
        add_contacts::add_contacts_response responce;
        try{
            if (!request.ParseFromString(req.body))
                throw contact_exception("add_contacts_request反序列化失败!");
            // 2.拿到数据，新增联系人信息
            print_contacts(request);
            // 3.构造的resp->resp->bpdy
            responce.set_success(true);
            responce.set_uid(generate_hex(10));
            // 4.序列化resp
            std::string responce_str;
            if(!responce.SerializeToString(&responce_str))
                throw contact_exception("add_contacts_response序列化失败");
            res.status = 200;
            res.body = responce_str;
            res.set_header("Content-Type", "application/protobuf");
            }
            catch(const contact_exception& message)
            {
                res.status = 500;
                responce.set_success(false);
                responce.set_error_desc(message.what());
                std::string responce_str;
                if(responce.SerializeToString(&responce_str))
                {
                    res.body = responce_str;
                    res.set_header("Content-Type", "application/protobuf");
                }
                std::cout << "/contacts/add 发生异常，异常信息：" << message.what() << std::endl;
            } });
    server.listen("0.0.0.0",8085);
    return 0;
}
